import { reactive } from 'vue';
<template>
	<el-dialog v-model="state.dialogVisible" title="字典值管理" width="60%">
		<template #footer>
			<div class="dialog-footer">
				<el-button @click="state.dialogVisible = false">取消</el-button>
				<el-button type="primary" @click="submit()">
					确定
				</el-button>
			</div>
		</template>
		<div class="w-100" style="height: 69vh">
			<div class="w-100 hr-flex-start">
				<span style="margin-right: 10px">应用名称:</span>
				<el-select v-model="state.currentApp" class="flex-1" placeholder="请选择应用名称" size="large" @change="selectChange">
					<el-option v-for="(item, index) in state.appList" :key="index" :label="item.label" :value="item.value" />
				</el-select>
			</div>
			<div class="w-100 hr-flex" style="margin-top: 20px;">
				<span style="margin-right: 10px">菜单权限:</span>
				<div class="flex-1">
					<el-tree
						ref="treeRef"
						node-key="id"
						show-checkbox 
						:data="state.currentAppMenu" 
						:props="defaultProps" 
						:default-checked-keys="getCurrentExistedMenu"
						:default-expand-all="true"
						:check-strictly="false"
						@check="checkChange" 
					/>
				</div>
			</div>
		</div>
	</el-dialog>
</template>
<script lang="ts" setup>
import { filter } from 'lodash';
import { reactive, defineExpose, computed, ref } from 'vue';
import request from '/@/api/develop/tenant';
import { TreeMenuTypes, MenuTree } from '/@/types/system/tenant';

const defaultProps = {
	children: 'children',
	label: 'title',
};

// 已选菜单类型
type SelectMenuJson = {
	appCode: string;
	menuIdList: number[];
}


// state类型
type StateTypes = {
	dialogVisible: boolean;
	appList: { label: string; value: string | number }[];
	currentApp: string;
	allMenuList: MenuTree[];
	currentAppMenu: MenuTree[];
	currentId: string|number;
	existedMenu: SelectMenuJson[];
	allParentNodeIds: any[];
};


const treeRef = ref()

const state = reactive<StateTypes>({
	dialogVisible: false,
	appList: [],
	currentApp: '',
	allMenuList: [] as any,
	currentAppMenu: [] as any,
	currentId: '',
	existedMenu: [],
	allParentNodeIds: [],
});

// 弹框控制
const dialogControl = async (id: string) => {
	state.dialogVisible = !state.dialogVisible;
	state.currentId = id
	getTreeMenu();
};


// 获取已授权菜单数据
const getAuthedMenu = async (id: string|number = '') => {
	let res = await request.sysTenantOwnMenu<SelectMenuJson[]>({id})
	state.existedMenu = res.data
}

// 获取app 和 树形菜单数据
const getTreeMenu = async () => {
	let res = await request.sysMenuTreeForGrant<TreeMenuTypes>();
	let appList = res.data?.appList?.map((item) => {
		return {
			label: item.appName,
			value: item.appCode,
		};
	});
	state.appList = appList;
	state.allMenuList = res.data?.menuTree;

	// 获取所有的父节点
	state.allParentNodeIds = getParentNodeId(res.data?.menuTree)

	state.currentApp = state.appList?.[0].value

	await getAuthedMenu(state.currentId)

	// 默认显示第一个
	state.currentApp && selectChange(state.currentApp)
};

// 应用切换事件
const selectChange = (val: string | number) => {
	let filterArr = state.allMenuList.filter((item) => {
		return item.appCode == val;
	});
	state.currentAppMenu = filterArr;
};

// 获取所有所有选中的菜单的id
const getCurrentExistedMenu = computed(() => {
	let filterArr = state.existedMenu.filter ( item => {
		return item.appCode == state.currentApp
	})

	// 当前应用选中的ID(包括全选中和半选中)
	let selectedIdArr = filterArr?.[0]?.menuIdList || []

	// 剔除半选中的ID，也就剔除父ID
	let newArr: number[]  = []

	if (selectedIdArr.length) {
		selectedIdArr.forEach( item => {
			let isExisted = state.allParentNodeIds.some( k => {
				return k == item
			})
			if (!isExisted) {
				newArr.push(item)
			}
		})
	}
	return newArr
})

// 点击复选框时触发的事件
const checkChange = () => {
	let allCheckedNodes = treeRef.value!.getCheckedNodes(false, true)
	console.log(allCheckedNodes)

	let allCheckedNodesIds: number[] = allCheckedNodes?.map( (item: any) => {
		return item.id
	}) || []


	let isExistedAppCode = state.existedMenu.some( item => {
		return item.appCode == state.currentApp
	})

	// 如果找不到就插入一条
	if (!isExistedAppCode) {
		state.existedMenu.push({
			appCode: state.currentApp,
			menuIdList: []
		})
	}
	state.existedMenu.forEach( item => {
		if(item.appCode == state.currentApp) {
			item.menuIdList = allCheckedNodesIds
		} else {

		}
	})

	// console.log(state.existedMenu)
}

// 提交已选中的菜单数据
const submit = async () => {
	let menuList: number[] = []
	state.existedMenu.forEach( item => {
		menuList = [...menuList, ...item.menuIdList]
	})
	await request.saveSelectedMenu({
		grantMenuIdList: menuList,
		id: state.currentId
	})
	state.dialogVisible = false
}
// 获取父节点的ID
const getParentNodeId = (arr: any) => {
	if (!arr.length) return [];
	let idArr = [] as any[]
	for(let i = 0; i < arr.length; i++) {
		let item = arr[i]
		if (item.children && item.children.length) {
			idArr.push(item.id)
			let childIds: any = getParentNodeId(item.children)
			idArr = [...idArr, ...childIds]
		}
	}
	return idArr
}

defineExpose({
	dialogControl,
});
</script>
